package com.gotye.particlesystem.programs;

import android.content.Context;
import android.opengl.GLES20;

import com.gotye.particlesystem.R;
import com.gotye.particlesystem.util.Geometry.Vector;

/**
 * Created by Michael.Ma on 2016/3/3.
 */
public class TextureShaderProgram extends ShaderProgram {
    // Uniform locations
    private final int uMatrixLocation;
    private final int uMVMatrixLocation;
    private final int uLightPosLocation;
    private final int uTextureUnitLocation;

    // Attribute locations
    private final int aPositionLocation;
    private final int aTextureCoordinatesLocation;
    private final int aNormalLocation;

    public TextureShaderProgram(Context context) {
        super(context, R.raw.texture_vertext_shader, R.raw.texture_fragment_shader);

        // Retrieve uniform locations for the shader program
        uMatrixLocation = GLES20.glGetUniformLocation(program, U_MATRIX);
        checkLocation(uMatrixLocation, U_MATRIX);
        uMVMatrixLocation = GLES20.glGetUniformLocation(program, U_MV_MATRIX);
        checkLocation(uMVMatrixLocation, U_MV_MATRIX);
        uLightPosLocation = GLES20.glGetUniformLocation(program, U_LIGHT_POS);
        checkLocation(uLightPosLocation, U_LIGHT_POS);
        uTextureUnitLocation = GLES20.glGetUniformLocation(program, U_TEXTURE_UNIT);
        checkLocation(uTextureUnitLocation, U_TEXTURE_UNIT);

        //Retrieve attribute locations for the shader program
        aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION);
        checkLocation(aPositionLocation, A_POSITION);
        aTextureCoordinatesLocation = GLES20.glGetAttribLocation(program, A_TEXTURE_COORDINATES);
        checkLocation(aTextureCoordinatesLocation, A_TEXTURE_COORDINATES);
        aNormalLocation = GLES20.glGetAttribLocation(program, A_NORMAL);
        checkLocation(aNormalLocation, A_NORMAL);
    }

    public void setUniforms(float[] matrix, float[] MVmatrix,
                            int textureId, Vector vectorLight) {
        // pass the matrix into the shader program
        GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
        GLES20.glUniformMatrix4fv(uMVMatrixLocation, 1, false, MVmatrix, 0);

        GLES20.glUniform3f(uLightPosLocation, vectorLight.x, vectorLight.y, vectorLight.z);

        // set the active texture unit to texture unit 0
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

        // bind the texture to this unit
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);

        // tell the texture uniform sampler to use this texture in the shader by
        // telling it to read from texture unit 0
        GLES20.glUniform1i(uTextureUnitLocation, 0);
    }

    public void setUniforms(float[] matrix, int[] textureIds) {
        // pass the matrix into the shader program
        GLES20.glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);

        for (int i=0;i<textureIds.length;i++) {
            // set the active texture unit to texture unit
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);

            // bind the texture to this unit
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);

            // tell the texture uniform sampler to use this texture in the shader by
            // telling it to read from texture unit 0
            GLES20.glUniform1i(uTextureUnitLocation, i);
        }
    }

    public int getPositionAttributeLocation() {
        return aPositionLocation;
    }

    public int getTextureCoordinatesAttributeLocation() {
        return aTextureCoordinatesLocation;
    }

    public int getNormalAttributeLocation() {
        return aNormalLocation;
    }
}
